/**
* \file		CalculTrajet.h
* \brief	Définit la structure CalculTrajet
* \details	Définition de la structure CalculTrajet et de ses fonctions associées
*/

#ifndef CASESTRAJET_H
#define CASESTRAJET_H

#include "Carte.h"
#include <stdlib.h>

/**
 *\struct       CalculTrajet
* \brief	Définition de la structure CalculTrajet.
* \details	Cette structure contient les informations pour réaliser le calcul de trajet avec l'algorithme A*
*/
struct CalcTraj
{
  Case* caseCarte;
  int coutDepAct;
  int coutActDest;
  int coutSomme;
  int xArr;
  int yArr;
  struct CalcTraj* parent;
  struct CalcTraj* calcSuivant;
  struct CalcTraj* calcPrecedent;

  int nbElements;
};
typedef struct CalcTraj CalculTrajet;

/**
 * \fn       void initCalcTraj(CalculTrajet* calcTraj)
 * \brief    initialise les valeurs d'une structure CalculTrajet.
 *
 * \param    calcTraj    pointeur sur une structure CalculTrajet à initialiser
 */
void initCalcTraj(CalculTrajet* calcTraj);

/**
 * \fn       void creerCalcTraj(CalculTrajet** calcTraj)
 * \brief    alloue une structure CalculTrajet dans la mémoire.
 *
 * \param    calcTraj    adresse d'un pointeur sur une structure CalculTrajet à allouer
 */
void creerCalcTraj(CalculTrajet** calcTraj);

void setCalcTraj(CalculTrajet* calcTraj, Carte* carte, int xDep, int yDep, int zDep, int xArr, int yArr);

/**
 * \fn       void ajoutCasesAdjacentes(CalculTrajet* listeOuverte, const CalculTrajet* listeFermee, CalculTrajet* dernièreCaseCarte)
 * \brief    ajoute les cases adjacentes à la liste ouverte
 * \details  ajoute les cases adjacentes à la liste ouverte en vérifiant si ceux-ci sont franchissables
 * \param    listeOuverte   liste dans laquelle seront ajoutées les cases valides pour être testées pour la création du chemin
 * \param    listeFermee    trajet déja validé jusqu'a maintenant et dans lequel la future case ajoutée ne doit pas se trouver
 * \param    caseAtuelle    case actuelle autours de laquelle vont être récupérées les cases adjacentes
 */
void ajoutCasesAdjacentes(Carte* carte, CalculTrajet** listeOuverte, CalculTrajet* listeFermee);

/**
 * \fn       CalculTrajet* meilleureCase(const CalculTrajet* listeOuverte)
 * \brief    renvois un pointeur sur la meilleure case de calcul de la liste ouverte
 * \details  compare les score des cases de la liste ouverte afin de renvoyer un pointeur sur celle de score optimale
 * \param    listeOuverte   pointeur sur la liste ouverte à tester
 */
CalculTrajet* meilleureCase(CalculTrajet* listeOuverte);

/**
 * \fn       void ajouterListeFermee(CalculTraj** listeFermee,CalculTrajet* listeOuverture, Case* caseAjout)
 * \brief    ajoute une case à la liste fermée afin de constituer le trajet final
 * \param    listeFermee   pointeur sur la liste fermée
 * \param    listeOuverte  pointeur sur la liste Ouverte
 * \param    caseAjout     pointeur sur la case à ajouter
 */
void ajouterListeFermee(CalculTrajet** listeFermee, CalculTrajet** listeOuverte, CalculTrajet* calcAjout);

/**
 * \fn       void ordonneChemin(CalculTrajet* listeFermee, CalculTrajet* listeTriee)
 * \brief    renvois une liste de case allant du départ du trajet à l'arrivée
 * \details  comme la liste fermée une fois générée se trouve dans l'ordre de l'arrivée au départ, cette fonction retourne celle-ci
 * \param    listeFermee   pointeur sur la liste fermée
 * \param    listeTriee    pointeur sur la liste dans l'ordre correct
 */
void ordonneChemin(CalculTrajet* listeFermee, CalculTrajet** listeTriee);

/**
 * \fn       void recherchePortionChemin(Carte* carte, int xDep, int yDep, int xArr, int yArr, int zChemin, Carte* carte)
 * \brief    applique l'algorithme A* dans une portion de chemin limitée à un étage
 * \param    carte      pointeur sur la carte de jeu
 * \param   xDep    coordonnée x de départ du chemin mesuré
 * \param   yDep    coordonnée y de départ du chemin mesuré
 * \param   xArr    coordonnée x d'arrivée du chemin mesuré
 * \param   yArr    coordonnée y d'arrivée du chemin mesuré
 * \param   zChemin profondeur de la portion actuelle
 * \param   portionTrajet  trajet de la portion désirée
 */
void recherchePortionChemin(Carte* carte, int xDep, int yDep, int xArr, int yArr, int zChemin, CalculTrajet** portionTrajet);

/**
 * \fn       int rechercheCoordonneeEscalier(const int zDep, const int zArr, const int xDep, const int yDep, int* xEscalier, int* yEscalier,Carte* carte)
 * \brief   recherche le passage le plus proche vers le niveau voulus
 * \param   zDep    coordonnée z de l'étage de départ
 * \param   zArr    coordonnée z de l'étage d'arrivée
 * \param   xDep    coordonnée x de départ
 * \param   yDep    coordonnée y de départ
 * \param   xEscalier    coordonnée x de l'escalier
 * \param   yEscalier    coordonnée y de l'escalier
 * \param   carte   pointeur sur la carte de jeu
 */
int rechercheCoordonneeEscalier(const int zDep, const int zArr, const int xDep, const int yDep, int* xEscalier, int* yEscalier,Carte* carte);

/**
 * \fn      CalculTrajet* rechercheChemin(int xDep, int yDep, int zDep, int xArr, int yArr, int zArr, Carte* carte) 
 * \brief    applique l'algorithme A* pour trouver le chemin entre deux points donnés
 * \details  si le chemin est calculé sur plusieurs niveaux celui-ci sera divisé en portion entre les escalier entre étages
 * \param   xDep    coordonnée x de départ du chemin mesuré
 * \param   yDep    coordonnée y de départ du chemin mesuré
 * \param   zDep    coordonnée z de départ du chemin mesuré
 * \param   xArr    coordonnée x d'arrivée du chemin mesuré
 * \param   yArr    coordonnée y d'arrivée du chemin mesuré
 * \param   zArr    coordonnée z d'arrivée du chemin mesuré
 * \param   carte   pointeur sur la carte de jeu
 */
CalculTrajet* rechercheChemin(int xDep, int yDep, int zDep, int xArr, int yArr, int zArr, Carte* carte);


/**
 * \fn       void testCalcTraj()
 * \brief    teste le module CalculTrajet
 */
void testCalculTrajet();

#endif
